/**
 * 2017:created by jordia
 * 20220304:[require] to [import]...jordia
 */
import {OrthographicCamera,Matrix4,Camera,Object3D} from 'three';
import Utils from '../general/utils';

/**
 * 斜测投影相机
 */
export default class cabinetCamera extends OrthographicCamera{
    constructor(left,right,top,bottom,near,far,angle,focusLength){
        super(left,right,top,bottom,near,far);
        this.isCabinetCamera=true;
        this.angle=angle!==undefined?angle:Math.PI/4;
        this.focusLength=focusLength!==undefined?focusLength:10;
        this.cabinetMatrix=new Matrix4();
        this.updateProjectionMatrix();
    }
    copy(source) {
        Camera.prototype.copy.call(this, source);
        this.left = source.left;
        this.right = source.right;
        this.top = source.top;
        this.bottom = source.bottom;
        this.near = source.near;
        this.far = source.far;
        this.zoom = source.zoom;
        this.angle = source.angle;
        this.focusLength = source.focusLength;
        this.cabinetMatrix=source.cabinetMatrix.clone();
        this.view = source.view === null ? null : Object.assign({}, source.view);
        return this;
    }
    clone(){
        let c=new cabinetCamera();
        c.copy(this);
        return c;
    }
    setViewOffset(fullWidth, fullHeight, x, y, width, height) {
        this.view = {
            fullWidth: fullWidth,
            fullHeight: fullHeight,
            offsetX: x,
            offsetY: y,
            width: width,
            height: height
        };
        this.updateProjectionMatrix();
    }
    clearViewOffset() {
        this.view = null;
        this.updateProjectionMatrix();
    }
    updateProjectionMatrix() {
        let dx = ( this.right - this.left ) / ( 2 * this.zoom );
        let dy = ( this.top - this.bottom ) / ( 2 * this.zoom );
        let cx = ( this.right + this.left ) / 2;
        let cy = ( this.top + this.bottom ) / 2;
        let left = cx - dx;
        let right = cx + dx;
        let top = cy + dy;
        let bottom = cy - dy;
        if (this.view !== null) {
            let zoomW = this.zoom / ( this.view.width / this.view.fullWidth );
            let zoomH = this.zoom / ( this.view.height / this.view.fullHeight );
            let scaleW = ( this.right - this.left ) / this.view.width;
            let scaleH = ( this.top - this.bottom ) / this.view.height;
            left += scaleW * ( this.view.offsetX / zoomW );
            right = left + scaleW * ( this.view.width / zoomW );
            top -= scaleH * ( this.view.offsetY / zoomH );
            bottom = top - scaleH * ( this.view.height / zoomH );
        }
        this.projectionMatrix.makeOrthographic(left, right, top, bottom, this.near, this.far);
        let offset = Math.sin(Math.PI / 4) * this.focusLength / 2;
        this.cabinetMatrix=Utils.makeCabinetShearMatrix(this.angle, -offset, -offset, 0).clone();
        this.projectionMatrix.multiply(this.cabinetMatrix);
    }
    toJSON(meta) {
        let data = Object3D.prototype.toJSON.call(this, meta);
        data.object.zoom = this.zoom;
        data.object.left = this.left;
        data.object.right = this.right;
        data.object.top = this.top;
        data.object.bottom = this.bottom;
        data.object.near = this.near;
        data.object.far = this.far;
        data.object.angle = this.angle;
        data.object.focusLength = this.focusLength;
        data.object.cabinetMatrix=this.cabinetMatrix.clone();
        if (this.view !== null) data.object.view = Object.assign({}, this.view);
        return data;
    }
}